<template>
  <div>
    <a-card>
      <a-form layout="inline">
        <a-form-item label="角色名">
          <a-input
            placeholder="请输入角色名称"
            :style="{ width: '300px' }"
            v-model:value="pageData.queryParams.name"
          />
        </a-form-item>
        <a-button type="primary" @click="queryData()" class="mr-2">
          查询
        </a-button>
        <a-button type="info"> 重置 </a-button>
      </a-form>
      <div class="table-operations">
        <a-button type="primary" @click="handleAdd">
          <template #icon>
            <plus-outlined />
          </template>
          添加角色
        </a-button>
      </div>
      <a-table
        :columns="columns"
        :data-source="tableData"
        :loading="loading"
        :pagination="false"
        bordered
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'action'">
            <a-button
              type="link"
              size="small"
              v-permission:disabled="'system_role_upd'"
              @click="handleEdit(record)"
            >
              编辑
            </a-button>
            <a-popconfirm
              title="确认删除吗?"
              ok-text="确认"
              cancel-text="取消"
              @confirm="handleDelete(record)"
            >
              <a-button
                type="link"
                size="small"
                v-permission:disabled="'system_role_del'"
              >
                删除
              </a-button>
            </a-popconfirm>
          </template>
        </template>
      </a-table>
      <div class="page-pagination">
        <a-pagination
          class="pagination"
          v-model:current="pageData.queryParams.page"
          v-model:page-size="pageData.queryParams.size"
          :defaultPageSize="pageData.queryParams.size"
          :page-size-options="['10', '20', '50', '100']"
          :total="total"
          showLessItems
          showSizeChanger
          @change="queryData"
          @showSizeChange="queryData"
        />
      </div>
    </a-card>
    <a-drawer
      placement="right"
      v-model:open="dialog.visible"
      :title="dialog.title"
      :width="502"
      :body-style="{ paddingBottom: '80px' }"
      :footer-style="{ textAlign: 'right' }"
      @close="closeModal"
    >
      <template #header> {{ dialog.title }} </template>
      <template #footer>
        <a-button type="primary" :loading="dialog.submitting" @click="confirmForm"
          >提交</a-button
        >&nbsp;
        <a-button>重置</a-button>
      </template>
      <a-spin :spinning="dialog.loading">
        <a-form
          ref="formRef"
          label-placement="left"
          :label-col="{ span: 4 }"
          :model="pageData.form"
          :rules="pageData.rules"
        >
          <a-form-item label="角色编码" name="code">
            <a-input
              v-model:value="pageData.form.code"
              placeholder="输入角色编码"
              :disabled="pageData.form.id"
            />
          </a-form-item>
          <a-form-item label="角色名称" name="name">
            <a-input v-model:value="pageData.form.name" placeholder="输入角色名" />
          </a-form-item>
          <a-form-item label="角色权限">
            <a-card>
              <a-tree
                checkable
                :virtual="true"
                :checkStrictly="false"
                :tree-data="treeData"
                @check="onCheck"
                v-model:checkedKeys="checkedKeys"
                v-model:expandedKeys="expandedKeys"
                style="max-height: 650px; overflow: hidden"
              />
            </a-card>
          </a-form-item>
          <a-form-item label="备注">
            <a-input
              v-model:value="pageData.form.description"
              type="textarea"
              placeholder="请输入备注"
            />
          </a-form-item>
        </a-form>
      </a-spin>
    </a-drawer>
  </div>
</template>
<script lang="ts" setup name="system_role">
import { unref, reactive, ref, onMounted } from "vue";
import { message } from "ant-design-vue";
import roleApi from "/@/api/system/role";
import permissionApi from "/@/api/system/menu/index";
import { RoleVo, RoleForm, RoleQuery } from "/@/api/system/role/types";
import { PageData, DialogOption } from '/@/types/global';
import { MenuVo } from "/@/api/system/menu/types";

const columns = [
  {
    title: "角色名称",
    dataIndex: "name",
    key: "name",
  },
  {
    title: "角色编码",
    dataIndex: "code",
    key: "code",
  },
  {
    title: "描述",
    dataIndex: "description",
    key: "description",
  },
  {
    title: "操作",
    key: "action",
  },
];

const defaultForm = {
  id: undefined,
  name: "",
  code: "",
  description: "",
  permissions: [],
};
const pageData = reactive<PageData<RoleForm, RoleQuery>>({
    form: {
      ...defaultForm,
    },
    queryParams: {
      page: 1,
      size: 10,
      name: '',
    },
    rules: {
      name: { required: true, message: "请输入角色名称", trigger: "blur" },
    }
})

const loading = ref(false);
const total = ref(0);
const tableData = ref<RoleVo[]>([]);
const queryData = async () => {
  try {
    loading.value = true;
    let _params = {
      ...unref(pageData.queryParams),
    };
    const { data } = await roleApi.getRoleList(_params);
    tableData.value = data.content;
    total.value = data.totalElements;
  } finally {
    loading.value = false;
  }
};

const allMenus = ref<any[]>([]);
onMounted(async () => {
  // 加载表格
  queryData();
  // 加载权限树
  const { data } = await permissionApi.getMenuTree();
  allMenus.value = data;
});

const dialog = reactive<DialogOption>({
  visible: false,
  title: '',
  loading: false,
  submitting: false
});
const formRef = ref();
const expandedKeys = ref([]);
const checkedKeys = ref([]);
// 包含选中与半选中
const checkedAllKeys = ref([] as any);
const treeData = ref([] as any);

const resetForm = () => {
  Object.assign(pageData.form, defaultForm);
  treeData.value = getTreeMenus(allMenus.value, []);
};

const closeModal = () => {
  // 重置表单
  resetForm();
  dialog.loading = false;
  checkedKeys.value = [];
  expandedKeys.value = [];
  treeData.value = [];
};

async function handleAdd() {
  dialog.visible = true;
  dialog.title = '新增角色';
  // 重置表单
  resetForm();
}

async function handleEdit(record: any) {
  dialog.loading = true;
  dialog.visible = true;
  dialog.title = '编辑角色';
  const { data } = await roleApi.getRoleInfo(record.id);
  Object.assign(pageData.form, data);
  treeData.value = getTreeMenus(allMenus.value, data.permissions);
  dialog.loading = false;
}

async function handleDelete(record: any) {
  await roleApi.deleteRoleInfo(record.id);
  message.success("删除成功");
  queryData();
}

function confirmForm(e: any) {
  e.preventDefault();
  dialog.submitting = true;
  formRef.value.validateFields().then(async () => {
    try {
      pageData.form.permissions = checkedAllKeys.value;
      if (!pageData.form.id) {
        await roleApi.addRoleInfo(pageData.form);
      } else {
        await roleApi.updateRoleInfo(pageData.form);
      }
      message.success("保存成功");
      dialog.submitting = false;
      dialog.visible = false;
      queryData();
    } finally {
      dialog.loading = false;
    }
  });
}

function getTreeMenus(permissions: MenuVo[], checkedPermissions: string[]) {
  return permissions.map((item: MenuVo) => {
    const children: any[] = item.children
      ? getTreeMenus(item.children, checkedPermissions)
      : [];
    if (checkedPermissions.indexOf(item.name) >= 0 && children.length == 0) {
      checkedKeys.value.push(item.name as never);
    }
    return {
      key: item.name,
      title: item.title,
      children: children,
      isLeaf: children.length == 0,
    };
  });
}

function onCheck(_checkedKeysValue: any, e: any) {
  const checkedNodes = e.checkedNodes.map((node: any) => node.key);
  const halfCheckedKeys = e.halfCheckedKeys;
  console.log(checkedNodes);
  console.log(halfCheckedKeys);
  checkedAllKeys.value = [...checkedNodes, ...halfCheckedKeys];
}
</script>